package com.hrs.core.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.hrs.common.enums.OrderStatus;
import com.hrs.common.enums.Status;
import com.hrs.common.result.Result;
import com.hrs.core.mapper.PayLogMapper;
import com.hrs.core.service.DepartmentService;
import com.hrs.core.service.PayLogService;
import com.hrs.enity.db.PayLog;
import com.hrs.enity.db.PayOrder;
import com.hrs.core.service.PayOrderService;
import com.hrs.core.mapper.PayOrderMapper;
import com.hrs.enity.dto.PayLogRegisterDto;
import com.hrs.enity.dto.PayLogViewDto;
import com.hrs.enity.dto.PayOrderViewDto;
import com.hrs.enity.ro.PayLogRegisterRo;
import com.hrs.enity.ro.PayOrderListRo;
import com.hrs.enity.vo.DepartmentVo;
import com.hrs.util.BeanUtil;
import com.hrs.util.DateTimeUtil;
import com.hrs.util.RequestUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
* @author 纱雾休比酱
* @description 针对表【t_pay_order(发放单)】的数据库操作Service实现
* @createDate 2023-01-13 10:06:01
*/
@Slf4j
@Service
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder>
    implements PayOrderService{

    @Autowired
    private PayOrderMapper payOrderMapper;

    @Autowired
    private PayLogService payLogService;
    @Autowired
    private PayLogMapper payLogMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<List<PayOrderViewDto>> listPayOrder(PayOrderListRo payOrderListRo) {
        String idKey = StringUtils.isNotBlank(payOrderListRo.getIdKey()) ? "%" + payOrderListRo.getIdKey() + "%" : null;
        String key = StringUtils.isNotBlank(payOrderListRo.getKey()) ? "%" + payOrderListRo.getKey() + "%" : null;

        Date time = payOrderListRo.getTime();
        if(Objects.isNull(time)) {
            time = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        OrderStatus status = payOrderListRo.getStatus();
        List<PayOrderViewDto> payOrderViewDtos = payOrderMapper.listPayOrder(year, month,
                status != null ? status.getKey() : null,idKey,key);
        if(payOrderViewDtos.size() == 0) {
            return Result.error("无数据");
        }

        //获取total
        List<Long> orderIds = payOrderViewDtos.stream().map(PayOrderViewDto::getId).collect(Collectors.toList());
        List<PayLogViewDto> payLogViewDtos = payLogMapper.listPayLog(orderIds);
        ConcurrentMap<Long, List<BigDecimal>> totalGroupByOid =
                payLogViewDtos.stream().collect(Collectors.groupingByConcurrent(PayLogViewDto::getOrderId,
                        Collectors.mapping(PayLogViewDto::getTotal, Collectors.toList())));
        payOrderViewDtos.forEach(f -> {
            List<BigDecimal> bigDecimals = totalGroupByOid.get(f.getId());
            if(bigDecimals != null) {
                BigDecimal total = new BigDecimal(0);
                for(BigDecimal b : bigDecimals) {
                    total = total.add(b);
                }

                f.setTotalBasicPay(total);
            }
        });
        return Result.success(payOrderViewDtos);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> initPay() {
        List<PayOrder> list = this.lambdaQuery().between(PayOrder::getMonth, DateTimeUtil.getPrecedMonthFirstDay(),
                DateTimeUtil.getThisMonthLastday()).list();
        if(list.size() != 0) {
            return Result.error("本月已初始化");
        }

        Set<Integer> deptIds = payOrderMapper.listNeedDeptIds(Status.NORMAL.getKey());
        List<PayOrder> payOrders = deptIds.stream().map(d -> {
            PayOrder payOrder = new PayOrder();
            payOrder.setMonth(new Date());
            payOrder.setStatus(OrderStatus.WAITING);
            payOrder.setDepartmentId(Integer.parseInt(d + ""));
            return payOrder;
        }).collect(Collectors.toList());
        this.saveBatch(payOrders);

        ImmutableMap<Integer, PayOrder> orderGroupByDeptId = Maps.uniqueIndex(payOrders,
                PayOrder::getDepartmentId);

        List<PayLogViewDto> payLogViewDtos = payLogMapper.initPayLog(Status.NORMAL.getKey());

        payLogViewDtos.forEach(f -> {
            PayOrder payOrder = orderGroupByDeptId.get(f.getDepartmentId());
            if(payOrder != null) {
                f.setOrderId(payOrder.getId());
            }
        });

        List<PayLog> payLogs = payLogViewDtos.stream().map(p -> {
            PayOrder payOrder = orderGroupByDeptId.get(p.getDepartmentId());
            if (payOrder != null) {
                p.setOrderId(payOrder.getId());
            }
            PayLog payLog = new PayLog();
            BeanUtils.copyProperties(p, payLog);
            return payLog;
        }).collect(Collectors.toList());

        payLogService.saveBatch(payLogs);

        return Result.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> registerLog(PayLogRegisterDto logRegisterDto) {
        Long orderId = logRegisterDto.getOrderId();
        PayOrder payOrder = this.getById(orderId);
        if(Objects.isNull(payOrder)) {
            return Result.error("对象不存在");
        }
        int key = payOrder.getStatus().getKey();
        if(key != OrderStatus.WAITING.getKey()) {
            return Result.error("不是待登记状态");
        }

        this.lambdaUpdate().eq(PayOrder::getId,orderId)
                .set(PayOrder::getRegisterId, RequestUserUtil.getRequestUserId())
                .set(PayOrder::getRegisterTime,new Date())
                .set(PayOrder::getStatus,OrderStatus.CHECKING)
                .update();

        List<PayLog> logSaveBatch = this.getLogSaveBatch(logRegisterDto.getPayLogRegisterRos(),orderId);
        if(logSaveBatch.size() != 0) {
            payLogService.updateBatchById(logSaveBatch);
        }

        return Result.success();
    }

    @Override
    public Result<String> reviewLog(PayLogRegisterDto logRegisterDto) {
        Long orderId = logRegisterDto.getOrderId();
        PayOrder payOrder = this.getById(orderId);
        if(Objects.isNull(payOrder)) {
            return Result.error("对象不存在");
        }
        int key = payOrder.getStatus().getKey();
        if(key != OrderStatus.CHECKING.getKey()) {
            return Result.error("不是待复核状态");
        }

        this.lambdaUpdate().eq(PayOrder::getId,orderId)
                .set(PayOrder::getReviewId, RequestUserUtil.getRequestUserId())
                .set(PayOrder::getReviewTime,new Date())
                .set(PayOrder::getStatus,OrderStatus.NORMAL)
                .update();

        List<PayLog> logSaveBatch = this.getLogSaveBatch(logRegisterDto.getPayLogRegisterRos(),orderId);
        if(logSaveBatch.size() != 0) {
            payLogService.updateBatchById(logSaveBatch);
        }

        return Result.success();
    }

    @Override
    public Result<List<PayLogViewDto>> listPayLog(Long orderId) {
        List<Long> orderIds = Collections.singletonList(orderId);
        List<PayLogViewDto> payLogViewDtos = payLogMapper.listPayLog(orderIds);
        return Result.success(payLogViewDtos);
    }

    private List<PayLog> getLogSaveBatch(List<PayLogRegisterRo> payLogRegisterRos,Long orderId) {
        Set<Long> ids = payLogRegisterRos.stream().map(PayLogRegisterRo::getId).collect(Collectors.toSet());
        List<PayLog> payLogs = payLogService.lambdaQuery()
                .eq(PayLog::getOrderId, orderId)
                .in(PayLog::getId,new ArrayList<>(ids))
                .list();
        ImmutableMap<Long, PayLogRegisterRo> roGroupById = Maps.uniqueIndex(payLogRegisterRos,
                PayLogRegisterRo::getId);
        Set<Long> updateIds = payLogs.stream().map(PayLog::getId).collect(Collectors.toSet());

        List<PayLog> result = new ArrayList<>();
        for (PayLog p : payLogs) {
            if(!updateIds.add(p.getId())) {
                PayLog payLog = new PayLog();
                PayLogRegisterRo payLogRegisterRo = roGroupById.get(p.getId());
                if(payLogRegisterRo != null) {
                    BeanUtils.copyProperties(payLogRegisterRo,payLog);
                    result.add(payLog);
                }
            }
        }
        return result;
    }
}




